// 版权所有2011 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package driver

import (
	"fmt"
	"reflect"
	"strconv"
	"time"
)

// ValueConverter是提供ConvertValue方法的接口。
// 
// 各种ValueConverter实现由
// 驱动程序包提供，以提供驱动程序之间转换的一致实现。ValueConverters有几种用途：
// 
// *将sql包
// 提供的值类型转换为数据库表的特定列类型，并确保其
// 适合，例如确保特定的int64适合
// 表的uint16列。
// 
// *将数据库中给定的值转换为
// 驱动程序值类型之一。
// 
// *由sql包提供，用于在扫描中从驱动程序的值类型
// 转换为用户的类型。
type ValueConverter interface {
	// ConvertValue将值转换为驱动程序值。
	ConvertValue(v any) (Value, error)
}

// Valuer是提供值方法的接口。
// 
// 实现Valuer接口的类型能够将
// 自身转换为驱动程序值。
type Valuer interface {
	// 值返回驱动程序值。
	// 值不能恐慌。
	Value() (Value, error)
}

// Bool是一个将输入值转换为Bool的值转换器。
// 
// 转换规则为：
// -布尔值返回不变
// -对于整数类型，
// 1为真
// 0为假，
// 其他整数为错误
// -对于字符串和[]字节，规则与strconv相同。ParseBool 
// -所有其他类型都是错误
var Bool boolType

type boolType struct{}

var _ ValueConverter = boolType{}

func (boolType) String() string { return "Bool" }

func (boolType) ConvertValue(src any) (Value, error) {
	switch s := src.(type) {
	case bool:
		return s, nil
	case string:
		b, err := strconv.ParseBool(s)
		if err != nil {
			return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
		}
		return b, nil
	case []byte:
		b, err := strconv.ParseBool(string(s))
		if err != nil {
			return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
		}
		return b, nil
	}

	sv := reflect.ValueOf(src)
	switch sv.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		iv := sv.Int()
		if iv == 1 || iv == 0 {
			return iv == 1, nil
		}
		return nil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", iv)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		uv := sv.Uint()
		if uv == 1 || uv == 0 {
			return uv == 1, nil
		}
		return nil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", uv)
	}

	return nil, fmt.Errorf("sql/driver: couldn't convert %v (%T) into type bool", src, src)
}

// Int32是一个值转换器，根据Int32值的限制将输入值转换为int64、
// 。
var Int32 int32Type

type int32Type struct{}

var _ ValueConverter = int32Type{}

func (int32Type) ConvertValue(v any) (Value, error) {
	rv := reflect.ValueOf(v)
	switch rv.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		i64 := rv.Int()
		if i64 > (1<<31)-1 || i64 < -(1<<31) {
			return nil, fmt.Errorf("sql/driver: value %d overflows int32", v)
		}
		return i64, nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		u64 := rv.Uint()
		if u64 > (1<<31)-1 {
			return nil, fmt.Errorf("sql/driver: value %d overflows int32", v)
		}
		return int64(u64), nil
	case reflect.String:
		i, err := strconv.Atoi(rv.String())
		if err != nil {
			return nil, fmt.Errorf("sql/driver: value %q can't be converted to int32", v)
		}
		return int64(i), nil
	}
	return nil, fmt.Errorf("sql/driver: unsupported value %v (type %T) converting to int32", v, v)
}

// String是一个将其输入转换为字符串的值转换器。
// 如果该值已经是字符串或[]字节，则该值不变。
// 如果该值是另一种类型，则使用fmt将其转换为字符串。Sprintf（“%v”，v）。
var String stringType

type stringType struct{}

func (stringType) ConvertValue(v any) (Value, error) {
	switch v.(type) {
	case string, []byte:
		return v, nil
	}
	return fmt.Sprintf("%v", v), nil
}

// Null是一种通过允许nil 
// 值但以其他方式委托给另一个ValueConverter来实现ValueConverter的类型。
type Null struct {
	Converter ValueConverter
}

func (n Null) ConvertValue(v any) (Value, error) {
	if v == nil {
		return nil, nil
	}
	return n.Converter.ConvertValue(v)
}

// NotNull是一种通过不允许nil 
// 值，但以其他方式委托给另一个ValueConverter来实现ValueConverter的类型。
type NotNull struct {
	Converter ValueConverter
}

func (n NotNull) ConvertValue(v any) (Value, error) {
	if v == nil {
		return nil, fmt.Errorf("nil value not allowed")
	}
	return n.Converter.ConvertValue(v)
}

// IsValue报告v是否为有效的值参数类型。
func IsValue(v any) bool {
	if v == nil {
		return true
	}
	switch v.(type) {
	case []byte, bool, float64, int64, string, time.Time:
		return true
	case decimalDecompose:
		return true
	}
	return false
}

// IsScanValue等于IsValue。
// 它的存在是为了兼容性。
func IsScanValue(v any) bool {
	return IsValue(v)
}

// DefaultParameterConverter是
// ValueConverter的默认实现，在Stmt未实现
// ColumnConverter时使用。
// 
// DefaultParameterConverter如果
// IsValue（arg），则直接返回其参数。否则，如果参数实现Valuer，则使用其
// Value方法返回一个值。作为备用方案，提供的
// 参数的基础类型用于将其转换为值：
// 基础整数类型转换为int64、浮点型转换为浮点型64、
// bool、string和[]字节。如果参数是nil 
// 指针，ConvertValue将返回一个nil值。如果参数是
// 非零指针，则会取消对它的引用，ConvertValue递归调用
// 。其他类型是错误的。
var DefaultParameterConverter defaultConverter

type defaultConverter struct{}

var _ ValueConverter = defaultConverter{}

var valuerReflectType = reflect.TypeOf((*Valuer)(nil)).Elem()

// callValuerValue返回vr。Value（），只有一个例外：
// If vr。Value是指针类型上自动生成的方法，而
// 指针为nil，它在运行时会在panicwrap 
// 方法中死机。把它当作零来对待。
// 第8415期。
// 
// 这样人们就可以实现驱动程序了。值类型上的值和
// 仍然使用指向这些类型的nil指针来表示nil/NULL，就像
// string/*string一样。
// 
// 此函数镜像在数据库/sql包中。
func callValuerValue(vr Valuer) (v Value, err error) {
	if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Pointer &&
		rv.IsNil() &&
		rv.Type().Elem().Implements(valuerReflectType) {
		return nil, nil
	}
	return vr.Value()
}

func (defaultConverter) ConvertValue(v any) (Value, error) {
	if IsValue(v) {
		return v, nil
	}

	switch vr := v.(type) {
	case Valuer:
		sv, err := callValuerValue(vr)
		if err != nil {
			return nil, err
		}
		if !IsValue(sv) {
			return nil, fmt.Errorf("non-Value type %T returned from Value", sv)
		}
		return sv, nil

	// 现在，继续选择Valuer接口，而不是decimal decompose接口。
	case decimalDecompose:
		return vr, nil
	}

	rv := reflect.ValueOf(v)
	switch rv.Kind() {
	case reflect.Pointer:
		// 间接指针
		if rv.IsNil() {
			return nil, nil
		} else {
			return defaultConverter{}.ConvertValue(rv.Elem().Interface())
		}
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return rv.Int(), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
		return int64(rv.Uint()), nil
	case reflect.Uint64:
		u64 := rv.Uint()
		if u64 >= 1<<63 {
			return nil, fmt.Errorf("uint64 values with high bit set are not supported")
		}
		return int64(u64), nil
	case reflect.Float32, reflect.Float64:
		return rv.Float(), nil
	case reflect.Bool:
		return rv.Bool(), nil
	case reflect.Slice:
		ek := rv.Type().Elem().Kind()
		if ek == reflect.Uint8 {
			return rv.Bytes(), nil
		}
		return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, ek)
	case reflect.String:
		return rv.String(), nil
	}
	return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
}

type decimalDecompose interface {
	// 分解将内部十进制状态返回为部分。
	// 如果提供的buf有足够的容量，可以将buf作为系数返回，
	// 根据需要设置值和长度。
	Decompose(buf []byte) (form byte, negative bool, coefficient []byte, exponent int32)
}
